/**
*	@class C3DSLoader
*
*	@brief
*
*	@author William McVicar
*/

#pragma once

#ifndef __3DSLOADER_H_INCLUDED__
#define __3DSLOADER_H_INCLUDED__

//  Library Includes

//  Local Includes
#include "../math/Vector2.h"
#include "../math/Vector3.h"
#include "../math/Vector4.h"

//  Macros
#define PRIMARY       0x4D4D

// Main Chunks
#define OBJECTINFO    0x3D3D				 
#define VERSION       0x0002				
#define EDITKEYFRAME  0xB000				

// Sub defines of OBJECTINFO
#define MATERIAL	  0xAFFF				
#define OBJECT		  0x4000				

// Sub defines of MATERIAL
#define MATNAME       0xA000				
#define MATDIFFUSE    0xA020				
#define MATMAP        0xA200				
#define MATMAPFILE    0xA300				

#define OBJECT_MESH   0x4100				

// Sub defines of OBJECT_MESH
#define OBJECT_VERTICES     0x4110			
#define OBJECT_FACES		0x4120			
#define OBJECT_MATERIAL		0x4130			
#define OBJECT_UV			0x4140	

//  Forward Declarations

//  Types
typedef struct tagFace
{
	i32 iVertIndex [ 3 ];
	i32 iCoordIndex[ 3 ];

} tFace;

typedef struct tagMaterialInfo
{
	c8	szName[ 255 ];
	c8	szFile[ 255 ];
	u8  colour[  3  ];
	i32 iTextureID;
	float fUTile;
	float fVTile;
	float fUOffset;
	float fVOffset;

} tMaterialInfo;

typedef struct tag3DObject
{
	c8			            szName[ 255 ];

	i32			            iNumVerts;
	i32			            iNumFaces;
	i32			            iNumTexVertex;
	i32			            iMaterialID;
	Protein::Vector3f*	pVerts;
	Protein::Vector3f*	pNormals;
	Protein::Vector2f*	pTexVerts;
	tFace*		          pFaces;

	bool bHasTexture;

} t3DObject;

typedef struct tag3DModel
{
	i32							 iNumOfObjects;
	i32							 iNumOfMaterials;

	std::vector< tMaterialInfo > materials;
	std::vector< t3DObject >	 object;

} t3DModel;

typedef struct tagIndices
{
	u16 a, b, c, bVisible;

} tIndices;

typedef struct tagChunk
{
	u16	usID;
	u32	uiLength;
	u32 uiBytesRead;

} tChunk;

//  Constants

//  Prototypes

namespace Protein
{

class C3DSLoader
{
	//Member Functions
public:

	C3DSLoader();
	~C3DSLoader();

	bool Import3DS( t3DModel* _pModel, const c8* _szFilename );

protected: 

private: 

	i32 GetString(c8 *);
	void ReadChunk(tChunk *);
	void ProcessNextChunk(t3DModel *pModel, tChunk *);
	void ProcessNextObjectChunk(t3DModel *pModel, t3DObject *pObject, tChunk *);
	void ProcessNextMaterialChunk(t3DModel *pModel, tChunk *);
	void ReadColorChunk(tMaterialInfo *pMaterial, tChunk *pChunk);
	void ReadVertices(t3DObject *pObject, tChunk *);
	void ReadVertexIndices(t3DObject *pObject, tChunk *);
	void ReadUVCoordinates(t3DObject *pObject, tChunk *);
	void ReadObjectMaterial(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk);
	void ComputeNormals(t3DModel *pModel);
	void CleanUp();

	//Member Variables
public:

protected: 

private: 

	FILE*	m_pFilePointer;

	tChunk*	m_pCurrentChunk;
	tChunk*	m_pTempChunk;

};

}

#endif //__3DSLOADER_H_INCLUDED__
